﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Web.Services.Description;
using System.Xml.Schema;
using System.Xml;

namespace BuildHelper.Admin
{
    public partial class WsdlCaller : Form
    {
        public WsdlCaller()
        {
            InitializeComponent();
            this.teWSDL.Text = @"http://localhost:8080/gcm/GcmWebServices/services/TotalQCIntegrationServiceSoap?wsdl";
        }
        private Wsdl wsdl;

        private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void btnReadWsdl_Click(object sender, EventArgs e)
        {
            wsdl =new Wsdl(teWSDL.Text);
        }
    }

    public class Wsdl
    {
        public string Url
        {
            get;
            private set;
        }
        public Wsdl(string url)
        {
            Url = url;
            Namespaces = new List<WsdlNamespace>();
            Methods = new List<WsdlMethod>();
            Messages = new List<WsdlMessage>();
            ReadWsdl();
        }
        private WsdlNamespace GetNamespace(XmlQualifiedName name)
        {
            foreach (WsdlNamespace w in Namespaces)
            {
                if (w.Name == name.Namespace)
                    return w;
            }
            WsdlNamespace ws = new WsdlNamespace(this, name.Namespace);
            return ws;
        }
        private  void ReadWsdl()
        {
            try
            {
                UriBuilder uriBuilder = new UriBuilder(Url);
                uriBuilder.Query = "WSDL";

                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
                webRequest.ContentType = "text/xml;charset=\"utf-8\"";
                webRequest.Method = "GET";
                webRequest.Accept = "text/xml";
                webRequest.Timeout = 10000;
                ServiceDescription serviceDescription;

                using (System.Net.WebResponse response = webRequest.GetResponse())
                using (System.IO.Stream stream = response.GetResponseStream())
                {
                    serviceDescription = ServiceDescription.Read(stream);
                }

                
                Types types = serviceDescription.Types;
                foreach (XmlSchema xmlSchema in types.Schemas)
                {
                    GetNamespace(xmlSchema);
                }
                
                int nCount = Namespaces.Count;

                for (int i = 0; i < nCount; i++)
                {
                    WsdlNamespace n = Namespaces[i];
                    int tCount = n.Types.Count;

                    for (int j = 0; j < tCount; j++)
                    {
                        WsdlType t = n.Types[j];
                        FillTypeInfo(t);
                    }
                }
                foreach (PortType portType in serviceDescription.PortTypes)
                {
                    foreach (Operation operation in portType.Operations)
                    {
                        Console.Out.WriteLine(operation.Name);

                        foreach (var message in operation.Messages)
                        {
                            if (message is OperationInput)
                                Console.Out.WriteLine("Input Message: {0}", ((OperationInput)message).Message.Name);
                            if (message is OperationOutput)
                                Console.Out.WriteLine("Output Message: {0}", ((OperationOutput)message).Message.Name);

                            foreach (System.Web.Services.Description.Message messagePart in serviceDescription.Messages)
                            {
                                if (messagePart.Name != ((OperationMessage)message).Message.Name) continue;

                                foreach (MessagePart part in messagePart.Parts)
                                {

                                }
                            }
                        }
                        Console.Out.WriteLine();
                    }
                } //End listing of types
            }
            catch
            { }
        }

        private  WsdlNamespace GetNamespace(XmlSchema xmlSchema)
        {
            WsdlNamespace n = new WsdlNamespace(this, xmlSchema);
            foreach (object item in xmlSchema.Items)
            {
                XmlSchemaElement schemaElement = item as XmlSchemaElement;
                XmlSchemaComplexType complexType = item as XmlSchemaComplexType;
                XmlSchemaSimpleType simpleType = item as XmlSchemaSimpleType;
                if (schemaElement != null)
                {
                    WsdlType t = new WsdlType(schemaElement, n);
                    //Console.Out.WriteLine("Schema Element: {0}", schemaElement.Name);

                    //XmlSchemaType schemaType = schemaElement.SchemaType;
                    //XmlSchemaComplexType schemaComplexType = schemaType as XmlSchemaComplexType;

                    //if (schemaComplexType != null)
                    //{
                    //    XmlSchemaParticle particle = schemaComplexType.Particle;
                    //    XmlSchemaSequence sequence =
                    //        particle as XmlSchemaSequence;
                    //    if (sequence != null)
                    //    {
                    //        foreach (XmlSchemaElement childElement in sequence.Items)
                    //        {
                    //            Console.Out.WriteLine("    Element/Type: {0}:{1}", childElement.Name,
                    //                                  childElement.SchemaTypeName.Name);
                    //        }
                    //    }
                    //}
                }
                else if (complexType != null)
                {
                    WsdlType t = new WsdlType(complexType, n);
                }
                else if(simpleType!=null)
                {
                    WsdlType t = new WsdlType(simpleType, n);
                }
            }
            return n;
        }
        private  void FillTypeInfo(WsdlType type, XmlSchemaParticle particle)
        {
            if (particle != null)
            {
                XmlSchemaSequence sequence = particle as XmlSchemaSequence;
                XmlSchemaChoice choice = particle as XmlSchemaChoice;
                XmlSchemaAll all = particle as XmlSchemaAll;
                if (sequence != null)
                {
                    for (int i = 0; i < sequence.Items.Count; i++)
                    {
                        XmlSchemaElement childElement = sequence.Items[i] as XmlSchemaElement;
                        XmlSchemaSequence innerSequence = sequence.Items[i] as XmlSchemaSequence;
                        XmlSchemaChoice innerChoice = sequence.Items[i] as XmlSchemaChoice;
                        XmlSchemaAll innerAll = sequence.Items[i] as XmlSchemaAll;

                        if (childElement != null)
                        {
                            WsdlParameter p = new WsdlParameter(childElement.Name);
                            WsdlNamespace nm = GetNamespace(childElement.SchemaTypeName);
                            p.Type = nm.GetType(childElement.SchemaTypeName.Name, childElement.SchemaTypeName);
                            p.MinOccurs = childElement.MinOccurs.AsInt();
                            p.MaxOccurs = childElement.MaxOccurs.AsInt();
                            type.Properties.Add(p);
                        }
                        else FillTypeInfo(type, sequence.Items[i] as XmlSchemaParticle);
                    }
                }
                else if (choice != null)
                {
                    for (int i = 0; i < choice.Items.Count; i++)
                    {
                        XmlSchemaElement childElement = choice.Items[i] as XmlSchemaElement;
                        XmlSchemaSequence innerSequence = choice.Items[i] as XmlSchemaSequence;
                        XmlSchemaChoice innerChoice = choice.Items[i] as XmlSchemaChoice;
                        XmlSchemaAll innerAll = choice.Items[i] as XmlSchemaAll;

                        if (childElement != null)
                        {
                            type.Choices.Add(childElement.Name);
                        }
                        else FillTypeInfo(type, choice.Items[i] as XmlSchemaParticle);
                    }
                }
                else if (all != null)
                {
                    Console.Out.WriteLine("  All");
                    for (int i = 0; i < all.Items.Count; i++)
                    {
                        XmlSchemaElement childElement = all.Items[i] as XmlSchemaElement;
                        XmlSchemaSequence innerSequence = all.Items[i] as XmlSchemaSequence;
                        XmlSchemaChoice innerChoice = all.Items[i] as XmlSchemaChoice;
                        XmlSchemaAll innerAll = all.Items[i] as XmlSchemaAll;

                        if (childElement != null)
                        {
                            WsdlParameter p = new WsdlParameter(childElement.Name);
                            WsdlNamespace nm = GetNamespace(childElement.SchemaTypeName);
                            p.Type = nm.GetType(childElement.SchemaTypeName.Name, childElement.SchemaTypeName);
                            p.MinOccurs = childElement.MinOccurs.AsInt();
                            p.MaxOccurs = childElement.MaxOccurs.AsInt();
                            type.Properties.Add(p);
                        }
                        else FillTypeInfo(type, all.Items[i] as XmlSchemaParticle);
                    }
                }
            }
        }
        public  void FillTypeInfo(WsdlType type)
        {
            XmlSchemaParticle particle = null;
            if (type.ComplexType != null)
            {
                if (type.ComplexType is XmlSchemaComplexType)
                    particle = ((XmlSchemaComplexType)(type.ComplexType)).Particle;
                else if (type.ComplexType is XmlSchemaSimpleType)
                {
                    XmlSchemaSimpleTypeRestriction restriction = (type.ComplexType as XmlSchemaSimpleType).Content as XmlSchemaSimpleTypeRestriction;
                    if (restriction != null)
                    {
                        foreach (XmlSchemaObject facet in restriction.Facets)
                        {
                            if (facet is XmlSchemaEnumerationFacet)
                                type.Choices.Add(((XmlSchemaEnumerationFacet)facet).Value);
                        }
                    }
                }
                else
                {

                }
            }
            else if (type.SchemaElement != null)
            {
                XmlSchemaComplexType schemaComplexType = type.SchemaElement.SchemaType as XmlSchemaComplexType;
                if (schemaComplexType != null)
                    particle = schemaComplexType.Particle;
            }
            FillTypeInfo(type, particle);
        }
        private  void OutputElements(XmlSchemaParticle particle)
        {
            XmlSchemaSequence sequence = particle as XmlSchemaSequence;
            XmlSchemaChoice choice = particle as XmlSchemaChoice;
            XmlSchemaAll all = particle as XmlSchemaAll;

            if (sequence != null)
            {
                Console.Out.WriteLine("  Sequence");

                for (int i = 0; i < sequence.Items.Count; i++)
                {
                    XmlSchemaElement childElement = sequence.Items[i] as XmlSchemaElement;
                    XmlSchemaSequence innerSequence = sequence.Items[i] as XmlSchemaSequence;
                    XmlSchemaChoice innerChoice = sequence.Items[i] as XmlSchemaChoice;
                    XmlSchemaAll innerAll = sequence.Items[i] as XmlSchemaAll;

                    if (childElement != null)
                    {
                        Console.Out.WriteLine("    Element/Type: {0}:{1}", childElement.Name,
                                              childElement.SchemaTypeName.Name);
                    }
                    else OutputElements(sequence.Items[i] as XmlSchemaParticle);
                }
            }
            else if (choice != null)
            {
                Console.Out.WriteLine("  Choice");
                for (int i = 0; i < choice.Items.Count; i++)
                {
                    XmlSchemaElement childElement = choice.Items[i] as XmlSchemaElement;
                    XmlSchemaSequence innerSequence = choice.Items[i] as XmlSchemaSequence;
                    XmlSchemaChoice innerChoice = choice.Items[i] as XmlSchemaChoice;
                    XmlSchemaAll innerAll = choice.Items[i] as XmlSchemaAll;

                    if (childElement != null)
                    {
                        Console.Out.WriteLine("    Element/Type: {0}:{1}", childElement.Name,
                                              childElement.SchemaTypeName.Name);
                    }
                    else OutputElements(choice.Items[i] as XmlSchemaParticle);
                }

                Console.Out.WriteLine();
            }
            else if (all != null)
            {
                Console.Out.WriteLine("  All");
                for (int i = 0; i < all.Items.Count; i++)
                {
                    XmlSchemaElement childElement = all.Items[i] as XmlSchemaElement;
                    XmlSchemaSequence innerSequence = all.Items[i] as XmlSchemaSequence;
                    XmlSchemaChoice innerChoice = all.Items[i] as XmlSchemaChoice;
                    XmlSchemaAll innerAll = all.Items[i] as XmlSchemaAll;

                    if (childElement != null)
                    {
                        Console.Out.WriteLine("    Element/Type: {0}:{1}", childElement.Name,
                                              childElement.SchemaTypeName.Name);
                    }
                    else OutputElements(all.Items[i] as XmlSchemaParticle);
                }
                Console.Out.WriteLine();
            }
        }

        public List<WsdlNamespace> Namespaces
        {
            get;
            private set;
        }
        public List<WsdlMethod> Methods
        {
            get;
            private set;
        }
        public List<WsdlMessage> Messages
        {
            get;
            private set;
        }
    }

    public class WsdlMethod
    {
        public WsdlMethod(string name = "")
        {
            Parameters = new List<WsdlParameter>();
            Name = name;
        }
        public string Name
        {
            get;
            set;
        }
        public List<WsdlParameter> Parameters
        {
            get;
            private set;
        }
        public WsdlParameter Result
        {
            get;
            set;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    public class WsdlParameter
    {
        public WsdlParameter(string name)
        {
            Name = name;
        }
        public string Name
        {
            get;
            set;
        }
        public int MinOccurs
        {
            get;
            set;
        }
        public int MaxOccurs
        {
            get;
            set;
        }
        public WsdlType Type
        {
            get;
            set;
        }

        public override string ToString()
        {
            return Name + " [" + Type.Name + "]";
        }
    }
    public class WsdlType
    {
        public WsdlType(string name, WsdlNamespace n)
        {
            if (name == "OperationType")
            {

            }
            if (name == "OperationInfo")
            {

            }
            Properties = new List<WsdlParameter>();
            Choices = new List<string>();
            Name = name;
            Namespace = n;
            if (n != null)
            {
                n.Types.Add(this);
            }
        }
        public WsdlType(XmlSchemaType type, WsdlNamespace n)
            : this(type.Name, n)
        {
            ComplexType = type;
        }
        public WsdlType(XmlSchemaElement el, WsdlNamespace n)
            : this(el.Name, n)
        {
            SchemaElement = el;
        }
        public XmlSchemaType ComplexType
        {
            get;
            private set;
        }
        public XmlSchemaElement SchemaElement
        {
            get;
            private set;
        }
        public string Name
        {
            get;
            set;
        }
        public List<WsdlParameter> Properties
        {
            get;
            private set;
        }
        public WsdlNamespace Namespace
        {
            get;
            set;
        }
        public List<string> Choices
        {
            get;
            private set;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    public class WsdlNamespace
    {
        public Wsdl Wsdl
        {
            get;
            private set;
        }
        public WsdlNamespace(Wsdl wsdl, string name)
        {
            Types = new List<WsdlType>();
            Name = name;
            Wsdl = wsdl;
            wsdl.Namespaces.Add(this);
        }
        public WsdlNamespace(Wsdl wsdl, XmlSchema schema)
            : this(wsdl, schema.TargetNamespace)
        {
            Schema = schema;
        }
        public XmlSchema Schema
        {
            get;
            private set;
        }
        public string Name
        {
            get;
            set;
        }
        public string ShortName
        {
            get;
            set;
        }
        public List<WsdlType> Types
        {
            get;
            private set;
        }
        public WsdlType GetType(string name, XmlQualifiedName el = null)
        {
            foreach (WsdlType t in Types)
                if (t.Name == name)
                    return t;

             WsdlType tp = null;
             if (el != null)
             {
                 tp = new WsdlType(name, this);
                 Wsdl.FillTypeInfo(tp);
             }
            return tp;
        }

        public override string ToString()
        {
            return Name;
        }
    }
    public class WsdlMessage
    {
        public WsdlMessage(string name, Wsdl wsdl)
        {
            Wsdl = wsdl;
            Name = name;
            Parameters = new List<WsdlParameter>();
        }
        public Wsdl Wsdl
        {
            get;
            private set;
        }
        public string Name
        {
            get;
            private set;
        }
        public WsdlType Type
        {
            get;
            set;
        }
        public List<WsdlParameter> Parameters
        {
            get;
            private set;
        }
    }
}
